/**
 * @file audio_manager.cc
 * @brief 🎧 音频管理器实现文件
 * 
 * 这里实现了audio_manager.h中声明的所有功能。
 * 主要包括录音缓冲区管理、音频播放控制和流式播放。
 */

extern "C" {
#include <string.h>
#include "esp_log.h"
#include "bsp_board.h"
}

#include "audio_manager.h"
#include "https_client.h"

// 定义静态成员
const char* AudioManager::TAG = "AudioManager";
uint8_t AudioManager::silent_data[4096];

AudioManager::AudioManager(uint32_t sample_rate, uint32_t recording_duration_sec, uint32_t response_duration_sec)
    : sample_rate(sample_rate)
    , recording_duration_sec(recording_duration_sec)
    , response_duration_sec(response_duration_sec)
    , recording_buffer(nullptr)
    , recording_buffer_size(0)
    , recording_length(0)
    , is_recording(false)
    , response_buffer(nullptr)
    , response_buffer_size(0)
    , response_length(0)
    , response_played(false)
    , streaming_state(STREAMING_IDLE)
    , streaming_buffer(nullptr)
    , streaming_buffer_size(STREAMING_BUFFER_SIZE)
    , streaming_write_pos(0)
    , streaming_read_pos(0)
{
    // 🧮 计算所需缓冲区大小
    recording_buffer_size = sample_rate * recording_duration_sec;  // 录音缓冲区（样本数）
    response_buffer_size = sample_rate * response_duration_sec * sizeof(int16_t);  // 响应缓冲区（字节数）
}

// 静态定时器回调函数
static void timeout_callback(TimerHandle_t xTimer) {
    AudioManager* manager = (AudioManager*)pvTimerGetTimerID(xTimer);
    if (manager == nullptr || !manager->waiting_for_data) {
        return;
    }

    ESP_LOGW("AudioManager", "流式播放超时，插入静音数据");
    
    // 使用静态分配的静音数据缓冲区
    memset(AudioManager::silent_data, 0, sizeof(AudioManager::silent_data));
    
    // 播放静音数据
    esp_err_t ret = bsp_play_audio_stream(AudioManager::silent_data, sizeof(AudioManager::silent_data));
    if (ret != ESP_OK) {
        ESP_LOGE("AudioManager", "播放静音数据失败: %s", esp_err_to_name(ret));
    }
}

AudioManager::~AudioManager() {
    // 删除定时器
    if (timeout_timer != nullptr) {
        xTimerDelete(timeout_timer, portMAX_DELAY);
        timeout_timer = nullptr;
    }
    deinit();
}

esp_err_t AudioManager::init() {
    ESP_LOGI(TAG, "初始化音频管理器...");
    
    // 分配录音缓冲区
    recording_buffer = (int16_t*)malloc(recording_buffer_size * sizeof(int16_t));
    if (recording_buffer == nullptr) {
        ESP_LOGE(TAG, "录音缓冲区分配失败，需要 %zu 字节", 
                 recording_buffer_size * sizeof(int16_t));
        return ESP_ERR_NO_MEM;
    }
    ESP_LOGI(TAG, "✓ 录音缓冲区分配成功，大小: %zu 字节 (%lu 秒)", 
             recording_buffer_size * sizeof(int16_t), (unsigned long)recording_duration_sec);
    
    // 分配双PSRAM缓冲区
    response_buffer1 = (int16_t*)heap_caps_malloc(response_buffer_size, MALLOC_CAP_SPIRAM);
    response_buffer2 = (int16_t*)heap_caps_malloc(response_buffer_size, MALLOC_CAP_SPIRAM);
    if (response_buffer1 == nullptr || response_buffer2 == nullptr) {
        ESP_LOGE(TAG, "响应音频双缓冲区分配失败，需要 %zu 字节", response_buffer_size * 2);
        free(recording_buffer);
        recording_buffer = nullptr;
        return ESP_ERR_NO_MEM;
    }
    memset(response_buffer1, 0, response_buffer_size);
    memset(response_buffer2, 0, response_buffer_size);
    response_buffer1_length = 0;
    response_buffer2_length = 0;
    current_response_buffer = false;
    buffer_ready_flag = false;
    
    // 保留原有response_buffer用于兼容
    response_buffer = (int16_t*)calloc(response_buffer_size / sizeof(int16_t), sizeof(int16_t));
    if (response_buffer == nullptr) {
        ESP_LOGE(TAG, "兼容响应缓冲区分配失败，需要 %zu 字节", response_buffer_size);
        heap_caps_free(response_buffer1);
        heap_caps_free(response_buffer2);
        free(recording_buffer);
        recording_buffer = nullptr;
        response_buffer1 = nullptr;
        response_buffer2 = nullptr;
        return ESP_ERR_NO_MEM;
    }
    ESP_LOGI(TAG, "✓ 双PSRAM缓冲区分配成功，每个大小: %zu 字节 (%lu 秒)", 
             response_buffer_size, (unsigned long)response_duration_sec);
    
    // 分配PSRAM主缓冲区
    streaming_buffer = (uint8_t*)heap_caps_malloc(streaming_buffer_size, MALLOC_CAP_SPIRAM);
    if (streaming_buffer == nullptr) {
        ESP_LOGE(TAG, "PSRAM流式播放缓冲区分配失败，需要 %zu 字节", streaming_buffer_size);
        free(recording_buffer);
        free(response_buffer);
        recording_buffer = nullptr;
        response_buffer = nullptr;
        return ESP_ERR_NO_MEM;
    }
    memset(streaming_buffer, 0, streaming_buffer_size);

    // 分配DMA二级缓冲区
    dma_buffer = (uint8_t*)malloc(DMA_BUFFER_SIZE);
    if (dma_buffer == nullptr) {
        ESP_LOGE(TAG, "DMA播放缓冲区分配失败，需要 %zu 字节", DMA_BUFFER_SIZE);
        heap_caps_free(streaming_buffer);
        free(recording_buffer);
        free(response_buffer);
        streaming_buffer = nullptr;
        recording_buffer = nullptr;
        response_buffer = nullptr;
        return ESP_ERR_NO_MEM;
    }
    memset(dma_buffer, 0, DMA_BUFFER_SIZE);

    ESP_LOGI(TAG, "✓ 流式播放缓冲区分配成功，PSRAM: %zu 字节, DMA: %zu 字节", 
             streaming_buffer_size, DMA_BUFFER_SIZE);
    
    return ESP_OK;
}

void AudioManager::deinit() {
    if (recording_buffer != nullptr) {
        free(recording_buffer);
        recording_buffer = nullptr;
    }
    
    if (response_buffer1 != nullptr) {
        heap_caps_free(response_buffer1);
        response_buffer1 = nullptr;
    }
    if (response_buffer2 != nullptr) {
        heap_caps_free(response_buffer2);
        response_buffer2 = nullptr;
    }
    if (response_buffer != nullptr) {
        free(response_buffer);
        response_buffer = nullptr;
    }
    
    if (dma_buffer != nullptr) {
        free(dma_buffer);
        dma_buffer = nullptr;
    }
    
    if (streaming_buffer != nullptr) {
        heap_caps_free(streaming_buffer);
        streaming_buffer = nullptr;
    }
}

// 🎙️ ========== 录音功能实现 ==========

void AudioManager::startRecording() {
    is_recording = true;
    recording_length = 0;
    ESP_LOGI(TAG, "开始录音...");
}

void AudioManager::stopRecording() {
    is_recording = false;
    ESP_LOGI(TAG, "停止录音，当前长度: %zu 样本 (%.2f 秒)", 
             recording_length, getRecordingDuration());
}

bool AudioManager::addRecordingData(const int16_t* data, size_t samples) {
    if (!is_recording || recording_buffer == nullptr) {
        return false;
    }
    
    // 📏 检查缓冲区是否还有空间
    if (recording_length + samples > recording_buffer_size) {
        ESP_LOGW(TAG, "录音缓冲区已满（超过10秒上限）");
        return false;
    }
    
    // 💾 将新的音频数据追加到缓冲区末尾
    memcpy(&recording_buffer[recording_length], data, samples * sizeof(int16_t));
    recording_length += samples;
    
    return true;
}

const int16_t* AudioManager::getRecordingBuffer(size_t& length) const {
    length = recording_length;
    return recording_buffer;
}

void AudioManager::clearRecordingBuffer() {
    recording_length = 0;
}

float AudioManager::getRecordingDuration() const {
    return (float)recording_length / sample_rate;
}

bool AudioManager::isRecordingBufferFull() const {
    return recording_length >= recording_buffer_size;
}

// 🔊 ========== 音频播放功能实现 ==========

void AudioManager::startReceivingResponse() {
    response_length = 0;
    response_played = false;
    response_buffer1_length = 0;
    response_buffer2_length = 0;
    current_response_buffer = false;
    buffer_ready_flag = false;
    ESP_LOGI(TAG, "🔄 重置所有响应缓冲区状态");
}

bool AudioManager::addResponseData(const uint8_t* data, size_t size) {
    if (!data || size == 0) {
        ESP_LOGE(TAG, "无效的音频数据");
        return false;
    }

    // 计算3秒音频数据大小
    size_t three_sec_size = sample_rate * 3 * sizeof(int16_t);
    
    // 确定当前使用的缓冲区
    int16_t* current_buf = current_response_buffer ? response_buffer2 : response_buffer1;
    size_t& current_len = current_response_buffer ? response_buffer2_length : response_buffer1_length;

    // 检查数据是否超过单个缓冲区大小
    if (size > response_buffer_size) {
        ESP_LOGW(TAG, "响应数据过大(%zu字节)，超过单个缓冲区大小(%zu字节)", size, response_buffer_size);
        return false;
    }

    // 检查当前缓冲区剩余空间
    if (current_len + size > response_buffer_size) {
        // 当前缓冲区即将满，标记为就绪并切换到另一个缓冲区
        buffer_ready_flag = true;     
        bsp_play_audio_async((const uint8_t*)current_buf, current_len);
        current_response_buffer = !current_response_buffer;
        current_buf = current_response_buffer ? response_buffer2 : response_buffer1;
        ESP_LOGI(TAG, "🔀 切换缓冲区到 %s current_len: %d", current_response_buffer ? "缓冲区2" : "缓冲区1", current_len);
        current_len = 0;
    }

    // 检查新缓冲区是否有足够空间
    if (current_len + size > response_buffer_size) {
        ESP_LOGW(TAG, "缓冲区空间不足: 需要 %zu 字节, 剩余 %zu 字节", 
                size, response_buffer_size - current_len);
        return false;
    }

    // 拷贝数据到当前缓冲区
    memcpy((uint8_t*)current_buf + current_len, data, size);
    current_len += size;
    if (current_response_buffer) {
        response_buffer2_length = current_len;
    } else {    
        response_buffer1_length = current_len;
    }
    // 如果达到3秒数据量，标记缓冲区就绪
    if (!buffer_ready_flag && current_len >= three_sec_size) {
        buffer_ready_flag = true;
        ESP_LOGI(TAG, "🆗 缓冲区已积累3秒音频数据(%zu字节)", current_len);
        
    }

    ESP_LOGI(TAG, "📦 追加音频数据: %zu 字节, 当前缓冲区: %s, 已存储: %zu 字节", 
             size, current_response_buffer ? "缓冲区2" : "缓冲区1", current_len);
    return true;
}

esp_err_t AudioManager::finishResponseAndPlay() {
    // 确定当前就绪的缓冲区
    int16_t* play_buf = current_response_buffer ? response_buffer1 : response_buffer2;
    size_t play_len = current_response_buffer ? response_buffer1_length : response_buffer2_length;
    
    if (play_len == 0) {
        // 如果没有数据可播放，生成静音数据
        play_len = sample_rate * sizeof(int16_t); // 1秒静音
        memset(play_buf, 0, play_len);
        ESP_LOGW(TAG, "🛑 没有音频数据，播放1秒静音");
    } else {
        ESP_LOGI(TAG, "📢 播放响应音频: %zu 样本 (%.2f 秒)",
                play_len / sizeof(int16_t), (float)play_len / (sample_rate * sizeof(int16_t)));
    }

    // 🔁 添加重试机制，确保音频可靠播放
    int retry_count = 0;
    const int max_retries = 3;
    esp_err_t audio_ret = ESP_FAIL;
    
    while (retry_count < max_retries && audio_ret != ESP_OK) {
        audio_ret = bsp_play_audio((const uint8_t*)play_buf, play_len);
        if (audio_ret == ESP_OK) {
            ESP_LOGI(TAG, "✅ 响应音频播放成功");
            response_played = true;
            break;
        } else {
            ESP_LOGE(TAG, "❌ 音频播放失败 (第%d次尝试): %s",
                    retry_count + 1, esp_err_to_name(audio_ret));
            retry_count++;
            if (retry_count < max_retries) {
                vTaskDelay(pdMS_TO_TICKS(100)); // 等100ms再试
            }
        }
    }

    // 清理已播放的缓冲区
    if (current_response_buffer) {
        memset(response_buffer1, 0, response_buffer_size);
        response_buffer1_length = 0;
    } else {
        memset(response_buffer2, 0, response_buffer_size);
        response_buffer2_length = 0;
    }
    
    // 重置标志
    buffer_ready_flag = false;
    ESP_LOGI(TAG, "🔄 已清理并重置缓冲区状态");
    
    return audio_ret;
}

esp_err_t AudioManager::playAudio(const uint8_t* audio_data, size_t data_len, const char* description) {
    ESP_LOGI(TAG, "播放%s...", description);
    esp_err_t ret = bsp_play_audio(audio_data, data_len);
    if (ret == ESP_OK) {
        ESP_LOGI(TAG, "✓ %s播放成功", description);
    } else {
        ESP_LOGE(TAG, "%s播放失败: %s", description, esp_err_to_name(ret));
    }
    return ret;
}


// 🌊 ========== 流式播放功能实现 ==========

// 原子操作辅助函数
static inline size_t atomic_read_pos(const volatile size_t* pos) {
    return __atomic_load_n(pos, __ATOMIC_SEQ_CST);
}

static inline void atomic_write_pos(volatile size_t* pos, size_t value) {
    __atomic_store_n(pos, value, __ATOMIC_SEQ_CST);
}

void AudioManager::startStreamingPlayback() {
    ESP_LOGI(TAG, "开始流式音频播放");
    streaming_state = STREAMING_PLAYING;
    atomic_write_pos(&streaming_write_pos, 0);
    atomic_write_pos(&streaming_read_pos, 0);
    
    // 清空缓冲区
    if (streaming_buffer) {
        memset(streaming_buffer, 0, streaming_buffer_size);
    }
}

bool AudioManager::addStreamingAudioChunk(const uint8_t* data, size_t size) {
    if (streaming_state != STREAMING_PLAYING || !streaming_buffer || !data) {
        ESP_LOGE(TAG, "无法添加流式音频块: 无效状态或参数");
        return false;
    }
    
    // 原子读取当前位置
    size_t write_pos = atomic_read_pos(&streaming_write_pos);
    size_t read_pos = atomic_read_pos(&streaming_read_pos);
    
    // 计算剩余空间
    size_t available_space;
    if (write_pos >= read_pos) {
        available_space = streaming_buffer_size - (write_pos - read_pos) - 1;
    } else {
        available_space = read_pos - write_pos - 1;
    }
    
    if (size > available_space) {
        ESP_LOGW(TAG, "流式缓冲区空间不足: 需要 %zu, 可用 %zu", size, available_space);
        return false;
    }
    
    // 写入数据
    size_t bytes_to_end = streaming_buffer_size - write_pos;
    if (size <= bytes_to_end) {
        memcpy(streaming_buffer + write_pos, data, size);
        atomic_write_pos(&streaming_write_pos, (write_pos + size) % streaming_buffer_size);
    } else {
        memcpy(streaming_buffer + write_pos, data, bytes_to_end);
        memcpy(streaming_buffer, data + bytes_to_end, size - bytes_to_end);
        atomic_write_pos(&streaming_write_pos, (size - bytes_to_end) % streaming_buffer_size);
    }
    
    ESP_LOGW(TAG, "添加流式音频块: %zu 字节, 写位置: %zu, 读位置: %zu", 
             size, atomic_read_pos(&streaming_write_pos), atomic_read_pos(&streaming_read_pos));
    if(atomic_read_pos(&streaming_read_pos) == 0){
        if (xTimerReset(timeout_timer, pdMS_TO_TICKS(100)) != pdPASS) {
            ESP_LOGE(TAG, "重置超时检测定时器失败");
        }
    } 
    // 播放流式音频数据
    TickType_t start_time = xTaskGetTickCount();
    processStreamingPlayback();
    return true;
}

void AudioManager::processStreamingPlayback() {
    if (streaming_state != STREAMING_PLAYING) {
        return;
    }

    // 计算缓冲数据量(毫秒)
    size_t write_pos = atomic_read_pos(&streaming_write_pos);
    size_t read_pos = atomic_read_pos(&streaming_read_pos);
    size_t buffered_bytes = (write_pos >= read_pos) ? 
                          (write_pos - read_pos) :
                          (streaming_buffer_size - read_pos + write_pos);
    size_t buffered_ms = buffered_bytes * 1000 / (sample_rate * sizeof(int16_t));

    // 使用二级缓冲架构
    size_t bytes_to_play = std::min(STREAMING_CHUNK_SIZE, 
                                   std::min(streaming_buffer_size - read_pos, 
                                           write_pos > read_pos ? write_pos - read_pos : streaming_buffer_size));
    
    if (bytes_to_play == 0) {
        return;
    }

    // 检查有效数据
    bool has_valid_data = false;
    for (size_t i = 0; i < bytes_to_play; i++) {
        if (streaming_buffer[read_pos + i] != 0) {
            has_valid_data = true;
            break;
        }
    }
    ESP_LOGI(TAG, "播放流式音频块: %zu 字节, 有效数据: %d", bytes_to_play, has_valid_data);

    memcpy(dma_buffer, streaming_buffer + read_pos, bytes_to_play);
    atomic_write_pos(&streaming_read_pos, (read_pos + bytes_to_play) % streaming_buffer_size);

    // 播放音频块
    esp_err_t ret = bsp_play_audio_stream(dma_buffer, bytes_to_play);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "流式播放失败: %s", esp_err_to_name(ret));
        
        // 错误恢复: 重试3次
        for (int i = 0; i < 3; i++) {
            vTaskDelay(pdMS_TO_TICKS(50));
            ret = bsp_play_audio_stream(dma_buffer, bytes_to_play);
            if (ret == ESP_OK) break;
        }
        
        if (ret != ESP_OK) {
            streaming_state = STREAMING_STOPPING;
            return;
        }
    }

    // 更新缓冲状态
    buffered_bytes = (write_pos >= atomic_read_pos(&streaming_read_pos)) ? 
                     write_pos - atomic_read_pos(&streaming_read_pos) :
                     streaming_buffer_size - atomic_read_pos(&streaming_read_pos) + write_pos;
    //延时一小段时间防止阻塞
    vTaskDelay(pdMS_TO_TICKS(5));
}

void AudioManager::finishStreamingPlayback() {
    if (streaming_state == STREAMING_IDLE) {
        return;
    }

    ESP_LOGI(TAG, "结束流式音频播放");
    streaming_state = STREAMING_STOPPING;
    
    // 播放最后的尾巴数据
    size_t remaining_data;
    size_t write_pos = atomic_read_pos(&streaming_write_pos);
    size_t read_pos = atomic_read_pos(&streaming_read_pos);
    
    if (write_pos >= read_pos) {
        remaining_data = write_pos - read_pos;
    } else {
        remaining_data = streaming_buffer_size - read_pos + write_pos;
    }
    
    if (remaining_data > 0) {
        uint8_t* remaining_buffer = (uint8_t*)malloc(remaining_data);
        if (remaining_buffer) {
            if (write_pos >= read_pos) {
                memcpy(remaining_buffer, streaming_buffer + read_pos, remaining_data);
            } else {
                size_t bytes_to_end = streaming_buffer_size - read_pos;
                memcpy(remaining_buffer, streaming_buffer + read_pos, bytes_to_end);
                memcpy(remaining_buffer + bytes_to_end, streaming_buffer, write_pos);
            }
            
            esp_err_t ret = bsp_play_audio(remaining_buffer, remaining_data);
            if (ret == ESP_OK) {
                ESP_LOGI(TAG, "✅ 播放剩余音频: %zu 字节", remaining_data);
            } else {
                ESP_LOGE(TAG, "❌ 播放剩余音频失败: %s", esp_err_to_name(ret));
            }
            
            free(remaining_buffer);
        }
    }
    bsp_audio_stop();   // 停止I2S输出防止噪音

    // 重置状态
    streaming_state = STREAMING_IDLE;
    atomic_write_pos(&streaming_write_pos, 0);
    atomic_write_pos(&streaming_read_pos, 0);
}

//响应式音频拉流播放
esp_err_t AudioManager::playHttpAudio(const char* url, bool is_https) {
    ESP_LOGI(TAG, "开始响应式播放HTTP音频: %s", url);
    
    // 创建HTTPS客户端
    HttpsClient client(url);
    
    // 设置数据接收回调
    client.setEventCallback([this](const HttpsClient::EventData& event) {
        if (event.type == HttpsClient::EventType::DATA_RECEIVED) {
            // 将收到的音频数据添加到响应缓冲区
            this->addResponseData(event.data, event.data_len);
        } else if (event.type == HttpsClient::EventType::DISCONNECTED) {
            // 响应数据接收完毕，播放响应音频
            this->finishResponseAndPlay();
        }
    });
    
    // 开始流式播放
    startReceivingResponse();
    // 发送GET请求获取音频数据
    esp_err_t ret = client.get("",15000); // 设置超时时间为15秒
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "HTTP请求失败: %s", esp_err_to_name(ret));
        stopHttpAudio();
        return ret;
    }
    
    return ESP_OK;
}

esp_err_t AudioManager::playHttpAudioStream(const char* url, bool is_https) {
    ESP_LOGI(TAG, "开始流式播放HTTP音频: %s", url);
    
    // 创建超时检测定时器
    if (timeout_timer == nullptr) {
        timeout_timer = xTimerCreate(
            "StreamTimeoutTimer",
            pdMS_TO_TICKS(STREAMING_TIMEOUT_MS),
            pdFALSE, // 单次定时器
            this,    // 传递this指针给回调
            timeout_callback
        );
        if (timeout_timer == nullptr) {
            ESP_LOGE(TAG, "创建超时检测定时器失败");
            return ESP_ERR_NO_MEM;
        }
        
    }

    // 创建HTTPS客户端
    HttpsClient client(url);
    
    // 设置数据接收回调
    client.setEventCallback([this](const HttpsClient::EventData& event) {
        if (event.type == HttpsClient::EventType::DATA_RECEIVED) {
            // 如果是第一次接收数据，启动定时器
            if (last_receive_time == 0) {
                last_receive_time = xTaskGetTickCount();
                waiting_for_data = true;
                if (xTimerStart(timeout_timer, pdMS_TO_TICKS(100)) != pdPASS) {
                    ESP_LOGE(TAG, "启动超时检测定时器失败");
                }
            } else {
                // 重置定时器
                if (xTimerReset(timeout_timer, pdMS_TO_TICKS(100)) != pdPASS) {
                    ESP_LOGE(TAG, "重置超时检测定时器失败");
                }
                last_receive_time = xTaskGetTickCount();
            }
            
            // 添加音频数据到流式缓冲区
            this->addStreamingAudioChunk(event.data, event.data_len);
        } else if (event.type == HttpsClient::EventType::DISCONNECTED) {
            // 停止定时器
            if (timeout_timer != nullptr) {
                xTimerStop(timeout_timer, pdMS_TO_TICKS(100));
            }
            waiting_for_data = false;
            last_receive_time = 0;
            
            // 停止播放
            stopHttpAudio();
        }
    });
    
    // 开始流式播放
    startStreamingPlayback();

    // 发送GET请求获取音频数据
    esp_err_t ret = client.get("",30000);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "HTTP请求失败: %s", esp_err_to_name(ret));
        // 停止定时器
        if (timeout_timer != nullptr) {
            xTimerStop(timeout_timer, pdMS_TO_TICKS(100));
        }
        waiting_for_data = false;
        last_receive_time = 0;
        
        stopHttpAudio();
        return ret;
    }
    
    return ESP_OK;
}


void AudioManager::stopHttpAudio() {
    finishStreamingPlayback();
    ESP_LOGI(TAG, "已停止HTTP音频播放");
}
